from abc import ABC, abstractmethod
from typing import Optional, Dict, Any, List
from enum import Enum
import asyncio
from io import BytesIO

class StorageProvider(str, Enum):
    """存储提供商"""
    MINIO = "minio"
    AWS_S3 = "aws_s3"
    ALIYUN_OSS = "aliyun_oss"
    QCLOUD_COS = "qcloud_cos"

class FileType(str, Enum):
    """文件类型"""
    IMAGE = "image"
    VIDEO = "video"
    AVATAR = "avatar"
    TEMP = "temp"

class StorageResponse:
    """存储响应"""
    def __init__(
        self,
        success: bool,
        file_url: Optional[str] = None,
        file_key: Optional[str] = None,
        error_message: Optional[str] = None,
        metadata: Optional[Dict[str, Any]] = None
    ):
        self.success = success
        self.file_url = file_url
        self.file_key = file_key
        self.error_message = error_message
        self.metadata = metadata or {}

class BaseStorageService(ABC):
    """对象存储服务抽象基类"""
    
    def __init__(self, config: Dict[str, Any]):
        self.config = config
        self.bucket_name = config.get("bucket_name")
        self.base_url = config.get("base_url")
    
    @abstractmethod
    async def upload_file(
        self, 
        file_data: bytes, 
        file_name: str, 
        file_type: FileType,
        content_type: str = "application/octet-stream"
    ) -> StorageResponse:
        """上传文件"""
        pass
    
    @abstractmethod
    async def upload_from_url(
        self, 
        source_url: str, 
        file_name: str, 
        file_type: FileType
    ) -> StorageResponse:
        """从URL上传文件"""
        pass
    
    @abstractmethod
    async def delete_file(self, file_key: str) -> bool:
        """删除文件"""
        pass
    
    @abstractmethod
    async def get_file_url(self, file_key: str, expires: int = 3600) -> Optional[str]:
        """获取文件访问URL"""
        pass
    
    @abstractmethod
    async def list_files(self, prefix: str = "", limit: int = 100) -> List[Dict[str, Any]]:
        """列出文件"""
        pass
    
    def generate_file_key(self, file_name: str, file_type: FileType, user_id: Optional[int] = None) -> str:
        """生成文件存储键"""
        import hashlib
        import datetime
        
        # 生成基于时间和用户ID的路径
        now = datetime.datetime.now()
        date_path = now.strftime("%Y/%m/%d")
        
        # 提取文件扩展名
        file_ext = file_name.split(".")[-1] if "." in file_name else "bin"
        
        # 生成唯一文件名
        unique_id = hashlib.md5(f"{file_name}_{now.timestamp()}_{user_id}".encode()).hexdigest()[:12]
        
        if user_id:
            return f"{file_type.value}/{date_path}/user_{user_id}/{unique_id}.{file_ext}"
        else:
            return f"{file_type.value}/{date_path}/{unique_id}.{file_ext}"